module PNEngine
  class Place < ActiveRecord::Base
    include Resource::InstanceMethods
    extend Resource::ClassMethods
    
    belongs_to :petrinet
    
    if Merb::Config[:use_reevaluation] == true
      has_many :tokens, :dependent => :delete_all, :finder_sql =>
        'SELECT * FROM tokens ' +
        'WHERE tokens.place_id = #{id} AND tokens.is_active = true'
    else
      has_many :tokens, :dependent => :delete_all
    end
    has_many :locators, :dependent => :delete_all
    has_many :arcs
    
    # Deletes all tokens with given case from place.
    def reset_tokens(c)
      self.tokens.find(:all, :conditions => ["case_id = ?", c.id]).collect{|t|t.destroy}
    end
    
    # Puts new token on place
    def push(token)
      #Merb.logger.info("#{self.tokens.size}")
      self.tokens << token
      #self.save!
      #self.reload
      #Merb.logger.info("#{self.tokens.size}")
    end
    
    # Consumes given token from place
    def pull(token)
      self.tokens.destroy(token.id)
      #self.save!
      #self.reload
    end
    
    # Produces Atom feed representation for place 
    def to_atom
      feed = Atom::Feed.new
      feed.title = name
      tokens.each do |token|
        feed << token.to_atom
      end
      feed
    end
		
    # Produces pnml representation for place
    def to_pnml(as_document = false)
      #TODO: only add token to pnml if it's not a pullplace with read-only set

      pnml_doc = REXML::Document.new
      pplace = pnml_doc.add_element('place', {'id' => pid})
			
      #add name if specified
      if name
        pname = pplace.add_element('name')
        ptext = pname.add_element('text')
        ptext.text = name
      end

      if feed_url || locators || tokens
        toolspecific = pplace.add_element('toolspecific', {'tool' => 'Petri Net Engine', 'version' => '1.0'})
				
        #add external
        toolspecific.add_element('external', {'type' => 'pull', 'href' => feed_url}) if feed_url
				
        #add locators
        if locators
          locators.each do |locator|
            plocator = toolspecific.add_element('locator')
            loc_name = plocator.add_element('name')
            loc_name.text = locator.name

            loc_type = plocator.add_element('type')
            loc_type.text = locator.val_type

            loc_expr = plocator.add_element('expr')
            loc_expr.text = locator.expr
          end
        end

        #add token references
        if tokens
          tokens.each do |token|
            toolspecific.add_element('token', {'href' => token.url})
          end
        end
      end

      output = ''
      as_document ? pnml_doc : pnml_doc.write(output, 2, true)
    end
    
    private
    before_update :sanitize
    #strips place name
    def sanitize
      self.name = self.name.strip
    end
    
    before_create :label_place
    def label_place
      self.name = self.pid if self.name.blank?
    end

  end
end
